package com.joinval.modules.sys.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.RectangleReadOnly;
import com.itextpdf.text.pdf.PdfWriter;
import com.joinval.common.enums.ResultCodeEnum;
import com.joinval.common.exception.JoinvalException;
import com.joinval.common.utils.*;
import com.joinval.common.validator.AssertUtils;
import com.joinval.modules.oss.minio.MinioUtils;
import com.joinval.modules.sys.dao.SysUserDao;
import com.joinval.modules.sys.dto.VolUserDTO;
import com.joinval.modules.sys.entity.*;
import com.joinval.modules.sys.enums.AuditStatusEnums;
import com.joinval.modules.sys.enums.UserStatusEnums;
import com.joinval.modules.sys.enums.UserTypeEnums;
import com.joinval.modules.sys.form.BaseWxLoginForm;
import com.joinval.modules.sys.form.SysUserInfoForm;
import com.joinval.modules.sys.service.*;
import com.joinval.modules.sys.vo.StampVO;
import com.joinval.modules.sys.vo.WxLoginVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.entity.ContentType;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 系统用户
 */
@Service("sysUserService")
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {

    @Value("${wxlogin.url}")
    private String wxloginUrl;
    @Value("${wxlogin.appid}")
    private String wxloginAppid;
    @Value("${wxlogin.secret}")
    private String wxloginSecret;
    @Value("${wxlogin.grantType}")
    private String wxloginGrantType;

    @Value("${wxImage.appid}")
    private String wxImageAppid;
    @Value("${wxImage.secret}")
    private String wxImageSecret;
    @Value("${wxImage.accessTokenUrl}")
    private String accessTokenUrl;
    @Value("${wxImage.grantType}")
    private String wxImageGrantType;
    @Value("${wxImage.imageUrl}")
    private String wxImageUrl;
    @Autowired
    private MinioUtils minioUtils;

    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysUserDetailService sysUserDetailService;
    @Autowired
    private SysUserAuditLogService sysUserAuditLogService;
    @Autowired
    private SysUserTokenService sysUserTokenService;
    @Autowired
    private SysRuleService sysRuleService;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String username = (String) params.get("username");
        Long createUserId = (Long) params.get("createUserId");

        IPage<SysUserEntity> page = this.page(
                new Query<SysUserEntity>().getPage(params),
                new QueryWrapper<SysUserEntity>()
                        .like(StringUtils.isNotBlank(username), "username", username)
                        .eq(createUserId != null, "create_user_id", createUserId)
        );

        return new PageUtils(page);
    }

    @Override
    public List<String> myPerms(Long userId) {
        if (userId == Constant.SUPER_ADMIN) {
            return baseMapper.queryAllPerms(null);
        }
        return baseMapper.queryAllPerms(userId);
    }
    @Override
    public SysUserEntity queryByUserName(String username) {
        return baseMapper.queryByUserName(username);
    }

    @Override
    @Transactional
    public void saveUser(SysUserEntity user) {
        // 手机号码验证
        Integer cnt = baseMapper.selectCount(new QueryWrapper<SysUserEntity>().eq("mobile", user.getMobile()));
        if (cnt > 0) {
            throw new JoinvalException("手机号码已经被注册，请联系管理员或者更换手机号!");
        }

        SysUserEntity sysUserEntity = queryByUserName(user.getUsername());
        if (sysUserEntity != null) {
            throw new JoinvalException("用户名: " + user.getUsername() + " 已存在!");
        }
        if(!RegularUtils.isPasswordLength(user.getPassword())) {
            throw new JoinvalException(ResultCodeEnum.PWD_LENGTH_ERROR.getMsg());
        }
        user.setUserType(UserTypeEnums.BG_USER.value());
        user.setCreateTime(new Date());
        //sha256加密
        String salt = RandomStringUtils.randomAlphanumeric(20);
        user.setPassword(new Sha256Hash(user.getPassword(), salt).toHex());
        user.setSalt(salt);
        user.setStatus(UserStatusEnums.ENABLE.value());
        this.save(user);
        //保存用户与角色关系
        sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());
    }

    @Override
    @Transactional
    public void update(SysUserEntity user) {
        //不修改密码
        user.setUsername(null);
        user.setPassword(null);
        user.setStatus(null);
        user.setUserType(null);
        this.updateById(user);
        //保存用户与角色关系
        sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());
    }

    @Override
    public void updateOwnInfo(SysUserEntity user) {
        SysUserEntity sysUserEntity = getById(user.getUserId());
        sysUserEntity.setGender(user.getGender());
        sysUserEntity.setBirthday(user.getBirthday());
        sysUserEntity.setMobile(user.getMobile());
        sysUserEntity.setRealName(user.getRealName());

        sysUserEntity.setLinkman(user.getLinkman());
        sysUserEntity.setCntPhone(user.getCntPhone());
        sysUserEntity.setCntAddress(user.getCntAddress());

        this.updateById(sysUserEntity);
    }

    @Override
    public void deleteBatch(Long[] userId) {
        this.removeByIds(Arrays.asList(userId));
    }

    @Override
    public boolean updatePassword(Long userId, String password, String newPassword) {
        SysUserEntity userEntity = new SysUserEntity();
        userEntity.setPassword(newPassword);
        return this.update(userEntity,
                new QueryWrapper<SysUserEntity>().eq("user_id", userId).eq("password", password));
    }


    /**
     * 新游客注册
     * @param baseWxLoginForm
     */
    public SysUserEntity wxLogin(BaseWxLoginForm baseWxLoginForm,String openId) {
        SysUserEntity sysUserEntity = baseMapper.selectOne(new QueryWrapper<SysUserEntity>().lambda().eq(SysUserEntity::getOpenId, openId));
        if(sysUserEntity == null){
            sysUserEntity = new SysUserEntity();
            String userNameNew = UUID.randomUUID().toString();
            userNameNew = userNameNew.substring(userNameNew.length() - 12);
            //1.2如果用户不存在，开始揭秘openid获取手机号
            JSONObject userInfo = JSON.parseObject(baseWxLoginForm.getRawData());
            // 将用户昵称解析到数据库中
            sysUserEntity.setRealName("游客_" + RandomStrUtils.getStringRandom(10)).setUsername(userNameNew).setStatus(UserStatusEnums.ENABLE.value())
                    .setUserType(UserTypeEnums.NORMAL_USER.value()).setOpenId(openId);
            log.info("新注册游客昵称为:游客_" + RandomStrUtils.getStringRandom(10));
            addUserType(sysUserEntity,UserTypeEnums.NORMAL_USER);
            baseMapper.insert(sysUserEntity);
            //游客
            SysUserDetail sysUserDetail = new SysUserDetail();
            sysUserDetail.setUserId(sysUserEntity.getUserId()).
                    setPoliceCheck(AuditStatusEnums.UN_PASSED.value()).setVolInfCheck(AuditStatusEnums.UN_PASSED.value()).
                    setVolLibCheck(AuditStatusEnums.UN_PASSED.value()).setCreateBy(sysUserEntity.getUserId());
            sysUserDetailService.save(sysUserDetail);
        }else {
            if (UserStatusEnums.DISABLE.equals(sysUserEntity.getStatus())) {
                throw new RuntimeException("账户已禁用");
            }
        }
        return sysUserEntity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized Map<String, Object> wxLogin(BaseWxLoginForm baseWxLoginForm) {
        log.info("用户登录开始================");
        JSONObject SessionKeyOpenId = getSessionKeyOrOpenId(baseWxLoginForm);
        String openId = SessionKeyOpenId.getString("openid");
        SysUserEntity sysUserEntity = wxLogin(baseWxLoginForm,openId);
        WxLoginVO wxLoginVO = new WxLoginVO();
        BeanUtils.copyProperties(sysUserEntity, wxLoginVO);
        SysUserDetail sysUserDetail = sysUserDetailService.getOne(new QueryWrapper<SysUserDetail>().lambda().eq(SysUserDetail::getUserId, sysUserEntity.getUserId()));
        BeanUtils.copyProperties(sysUserDetail, wxLoginVO);
        getTeamIdsByUserId(wxLoginVO,sysUserEntity.getUserId());
        addUnPassedMsg(wxLoginVO,sysUserEntity.getUserId());
        //生成token，并保存到数据库
        R r = sysUserTokenService.createToken(sysUserEntity.getUserId());
        r.put("wxLoginVO", wxLoginVO);
        return r;
    }


    void addUnPassedMsg(WxLoginVO wxLoginVO,Long userId){
        //分配审核拒绝原因
        if(AuditStatusEnums.UN_PASSED.value().equals(wxLoginVO.getOrgAuditStatus())){
            SysUserAuditLog lastOrgAuditLog = sysUserAuditLogService.getLastAuditLog(userId, UserTypeEnums.ORDER_USER);
            wxLoginVO.setOrgAuditMsg(lastOrgAuditLog.getAuditMsg());
        }
        if(AuditStatusEnums.UN_PASSED.value().equals(wxLoginVO.getVolAuditStatus())){
            SysUserAuditLog lastVolAuditLog = sysUserAuditLogService.getLastAuditLog(userId, UserTypeEnums.VOL_USER);
            wxLoginVO.setVolAuditMsg(lastVolAuditLog.getAuditMsg());
        }
    }

    private void addLog(Long userId, AuditStatusEnums auditStatusEnum,UserTypeEnums userTypeEnums) {
        // 新增审核信息表数据
        SysUserAuditLog sysUserAuditLog = new SysUserAuditLog();
        sysUserAuditLog.setUserId(userId).setAuditStatus(auditStatusEnum.value());
        sysUserAuditLog.setUserType(userTypeEnums.value());
        sysUserAuditLogService.save(sysUserAuditLog);
    }
    private String getLevelPic(List<SysRule> rules, BigDecimal serviceHour) {
        String levelPic = null;
        for (int i = 0; i < rules.size(); i++) {
            if (rules.get(0).getLevelHour().compareTo(serviceHour) == 1) {
                break;
            }
            if ((rules.get(i).getLevelHour().compareTo(serviceHour) == 0 || rules.get(i).getLevelHour().compareTo(serviceHour) == -1) &&
                    rules.get(i + 1).getLevelHour().compareTo(serviceHour) == 1) {
                levelPic = rules.get(i).getLevelPic();
                break;
            }
            if (rules.get(rules.size() - 1).getLevelHour().compareTo(serviceHour) == 0 ||
                    rules.get(rules.size() - 1).getLevelHour().compareTo(serviceHour) == -1
            ) {
                levelPic = rules.get(rules.size() - 1).getLevelPic();
                break;
            }
        }
        return levelPic;
    }

    private WxLoginVO getTeamIdsByUserId(WxLoginVO wxLoginVO, Long userId) {
        return wxLoginVO;
    }

    @Override
    public void dynamicQRCode(Long userId,HttpServletResponse response) {
        OutputStream outputStream = null;
        try {
            // 生成时间戳
            String now = String.valueOf(System.currentTimeMillis());
            log.info("生成的时间戳为:" + now);
            // 暂时定义为百度地址，后续加上时间戳
            byte[] qrCodeImage = QRCodeGeneratorUtils.getQRCodeImage("https://www.baidu.com");
            outputStream = response.getOutputStream();
//            response.reset();
//            // 设置response的Header
            response.addHeader("Content-Length", qrCodeImage.length + "");
            response.setContentType("image/png");
            outputStream.write(qrCodeImage);
            outputStream.flush();
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
    }

    @Override
    public PageUtils menuList(Page page, UserTypeEnums userType, AuditStatusEnums auditStatus,String orgCode, String volCode, String orgName, String realName, String mobile) {
        Page<Map<String, Object>> menuList = new Page<>();
        if(UserTypeEnums.VOL_USER.equals(userType)){
             menuList = baseMapper.menuList(page, userType == null ? null : userType.value(),null, auditStatus == null ? null : auditStatus.value()
                   ,orgCode, volCode, orgName, realName, mobile);
        }else if(UserTypeEnums.ORDER_USER.equals(userType)){
             menuList = baseMapper.menuList(page, userType == null ? null : userType.value(), auditStatus == null ? null : auditStatus.value(),null
                    ,orgCode, volCode, orgName, realName, mobile);
        }else {
            menuList = baseMapper.menuList(page, userType == null ? null : userType.value(), null,null
                    ,orgCode, volCode, orgName, realName, mobile);
        }
        PageUtils pageUtils = PageUtils.parseResult(menuList);
        return pageUtils;
    }

    @Override
    public Map<String, Object> loginUserInfo(Long userId) {
        return baseMapper.loginUserInfo(userId);
    }

    @Override
    public List<Map<String, Object>> getUserRolesByUserId(Long userId) {
        return baseMapper.getUserRolesByUserId(userId);
    }


    /**
     * 用户的角色code
     *
     * @param userId
     * @return
     */
    @Override
    public List<String> getUserRoleCodesByUserId(Long userId) {
        List<Map<String,Object>> list =  baseMapper.getUserRolesByUserId(userId);
        List<String> roleCodeList = new ArrayList<>(list.size());
        if (list.size()>0){
            for (Map<String,Object> map : list) {
                roleCodeList.add(MapUtils.getString(map,"roleCode"));
            }
        }
        return roleCodeList;
    }

    @Override
    public Map<String, Object> volUserInfo(Long userId) {
        Map<String, Object> userInfo = baseMapper.volUserInfo(userId);
        return userInfo;
    }

    @Override
    public Map<String, Object> volOrgInfo(Long userId) {
        Map<String, Object> orgInfo = baseMapper.volOrgInfo(userId);
        return orgInfo;
    }

    @Override
    public Map<String, Object> bgUserInfo(Long userId) {
        Map<String, Object> bgUserInfo = baseMapper.bgUserInfo(userId);
        if (bgUserInfo == null) {
            throw new JoinvalException("未找到该用户！");
        }
        List<Long> roleIdList = baseMapper.queryAllRoleId(userId);
        bgUserInfo.put("roleIdList", roleIdList);

        // 填充街镇信息
//        String townIdRes = bgUserInfo.get("townId")==null? null : bgUserInfo.get("townId").toString();
//        String[] arr = StringUtils.split(townIdRes, ",");
        List<String> nameList = new ArrayList<>();
//        if (townIdRes != null && arr != null ) {
//            for (String id : arr) {
//                if (townMap.containsKey(Integer.valueOf(id))) {
//                    nameList.add(townMap.get(Integer.valueOf(id)));
//                }
//            }
//        }
//        bgUserInfo.put("townIdList", arr);
        bgUserInfo.put("townNameList", nameList);
        bgUserInfo.put("townNameAppend", nameList.size()>0 ? String.join(",", nameList) : "");

        return bgUserInfo;
    }

    @Override
    public Result volUserCenter(Long userId, Set<Long> teamIds, Integer leaderStatus) {
        checkIsOneself(userId);
        Map<String, Object> volUserCenter = baseMapper.queryVolUserCenter(userId);
        String userType = volUserCenter.get("userType").toString();
        if (!StringUtils.isEmpty(userType) && userType.contains(UserTypeEnums.VOL_USER.value())) {
            BigDecimal serviceHour = BigDecimal.ZERO;
            if (volUserCenter.get("serviceHour") != null) {
                serviceHour = new BigDecimal(volUserCenter.get("serviceHour").toString());
            }
            List<SysRule> rules = sysRuleService.rules();
            Integer levelNum = getLevelNum(rules, serviceHour);
            volUserCenter.put("levelNum", levelNum);
        }
        if (!StringUtils.isEmpty(userType) && userType.contains(UserTypeEnums.ORDER_USER.value())) {

        }
        return Result.ok().data(volUserCenter);
    }


    private Integer getLevelNum(List<SysRule> rules, BigDecimal serviceHour) {
        Integer levelNum = null;
        for (int i = 0; i < rules.size(); i++) {
            if (rules.get(0).getLevelHour().compareTo(serviceHour) == 1) {
                levelNum = i;
                break;
            }
            if ((rules.get(i).getLevelHour().compareTo(serviceHour) == 0 || rules.get(i).getLevelHour().compareTo(serviceHour) == -1) &&
                    (rules.get(i + 1).getLevelHour().compareTo(serviceHour) == 1)) {
                levelNum = i + 1;
                break;
            }
            if (rules.get(rules.size() - 1).getLevelHour().compareTo(serviceHour) == -1 || rules.get(rules.size() - 1).getLevelHour().compareTo(serviceHour) == 0) {
                levelNum = rules.size();
                break;
            }
        }
        return levelNum;
    }


    @Override
    public PageUtils orgList(Page page, AuditStatusEnums auditStatus, String orgName, String orgLocation, String orgType, String realName, String mobile) {
        Page<Map<String, Object>> orgInfo = baseMapper.orgList(page, auditStatus == null ? null : auditStatus.value(),orgName, orgLocation, orgType, realName, mobile);
        return PageUtils.parseResult(orgInfo);
    }

    @Override
    public PageUtils volList(Page page, AuditStatusEnums auditStatus, Integer minAge, Integer maxAge, Integer minServiceHour, Integer maxServiceHour, String volCode, String realName, String mobile) {
        List<Long> userIds = new ArrayList<>();
        List<SysUserEntity> userList = this.list(new QueryWrapper<SysUserEntity>().lambda().apply(UserTypeEnums.VOL_USER.value() != null,"FIND_IN_SET ('"+UserTypeEnums.VOL_USER.value()+"',user_type)"));
        if (!CollectionUtils.isEmpty(userList)) {
            userIds = userList.stream().map(item -> item.getUserId()).collect(Collectors.toList());
        }
        List<Long> volUserId = baseMapper.getVolUserIdByAge(minAge, maxAge);
        userIds.retainAll(volUserId);
        if (CollectionUtils.isEmpty(userIds)) {
            return new PageUtils();
        }
        Page<Map<String, Object>> volInfo = baseMapper.volList(page, userIds, auditStatus == null ? null : auditStatus.value(), volCode, realName, mobile, minServiceHour, maxServiceHour);
        List<Map<String, Object>> records = volInfo.getRecords();
        addTeamInfo(records);
        return PageUtils.parseResult(volInfo);
    }

    @Override
    public PageUtils list(Page page, UserStatusEnums status, Integer gender, String idCard, String username,
                          String realName, String mobile,Long countryId,Long townId,Long roleId) {

        // 权限限制根据角色，限制区域 20240625
//        Long userId = ShiroUtils.getUserEntity().getUserId();
//        List<String> roleCodes = getUserRoleCodesByUserId(userId);
        List<Long> townIdsQry = new ArrayList<>();

        Page<Map<String, Object>> userlist = baseMapper.list(page, status == null ? null : status.value(), gender, idCard, username, realName,
                mobile,townId,roleId,countryId,townIdsQry);
        return PageUtils.parseResult(userlist);
    }

    @Override
    public PageUtils getUserListPageByRoleCode(Page page, UserStatusEnums userStatus, Integer gender, String idCard
            , String username, String realName, String mobile, String roleCode
            , Long countyId, Long townId, List<Long> townIdList) {

        Page<Map<String, Object>> userlist = baseMapper.getUserListPageByRoleCode(page, userStatus == null ? null : userStatus.value()
                , gender, idCard, username, realName, mobile,roleCode
                , countyId, townId, townIdList);


        // 填充街镇信息
//        Map<Integer, String> townMap = townService.getTowns();
//        for(Map<String, Object> map : userlist.getRecords()) {
//            String townIdRes = map.get("townId")==null? null : map.get("townId").toString();
//            String[] arr = StringUtils.split(townIdRes, ",");
//            List<String> nameList = new ArrayList<>();
//            for (String id : arr) {
//                if (townMap.containsKey(Integer.valueOf(id))) {
//                    nameList.add(townMap.get(Integer.valueOf(id)));
//                }
//            }
//            map.put("townIdList", arr);
//            map.put("townNameList", nameList);
//            map.put("townNameAppend", nameList.size()>0 ? String.join(",", nameList) : "");
//
//        }
        return PageUtils.parseResult(userlist);
    }

    @Override
    @Transactional
    public void orgUpdate(SysUserInfoForm sysUserInfoForm) {
        AssertUtils.notNull(sysUserInfoForm.getUserId(), "用户id主键不能为空");
        int row = this.baseMapper.updateLogoById(sysUserInfoForm.getLogo(), sysUserInfoForm.getUserId());
        int _row = sysUserDetailService.updateOrgInfo(sysUserInfoForm.getUserId(), sysUserInfoForm.getOrgLocation());
        if (row <= 0 || _row <= 0) {
            throw new RuntimeException("修改机构信息失败");
        }
    }

    void addTeamInfo(List<Map<String, Object>> volInfoList) {
        for (Map<String, Object> volInfo : volInfoList) {
            addTeamInfo(volInfo);
        }
    }

    void addTeamInfo(Map<String, Object> userInfo) {
        Long userId = Long.valueOf(userInfo.get("userId").toString());
        BigDecimal serviceHour = new BigDecimal(userInfo.get("serviceHour").toString());
        List<SysRule> rules = sysRuleService.rules();
        Integer levelNum = getLevelNum(rules, serviceHour);
        userInfo.put("levelNum", levelNum);
        List<Map<String, Object>> teamInfo = null;
        List<String> teamName = null;
        if (!CollectionUtils.isEmpty(teamInfo)) {
            teamName = teamInfo.stream().map(item -> item.get("teamName").toString()).collect(Collectors.toList());
        }
        userInfo.put("teamInfo", teamName);
    }

    private JSONObject getSessionKeyOrOpenId(BaseWxLoginForm baseWxLoginForm) {
        log.info("js_code为:" + baseWxLoginForm.getCode());
        log.info("用户非敏感信息:" + baseWxLoginForm.getRawData());
        log.info("签名:" + baseWxLoginForm.getSignature());
        log.info("敏感数据:" + baseWxLoginForm.getEncrypteData());
        log.info("解密算法向量:" + baseWxLoginForm.getIv());
        // 配置请求参数
        Map<String, Object> param = new HashMap<>();
        param.put("appid", wxloginAppid);
        param.put("secret", wxloginSecret);
        param.put("js_code", baseWxLoginForm.getCode());
        param.put("grant_type", wxloginGrantType);
        // 发送请求
        String wxResult = HttpClientUtils.sendGet(wxloginUrl, param);
        log.info("获取openId相关信息结果:" + wxResult);
        JSONObject jsonObject = JSONObject.parseObject(wxResult);
        log.info("openId=" +jsonObject.getString("openid") + ",session_key=" + jsonObject.getString("session_key"));
        return jsonObject;
    }

    /**
     * 检查角色是否越权
     */
    private void checkRole(SysUserEntity user) {
        if (user.getRoleIdList() == null || user.getRoleIdList().size() == 0) {
            return;
        }
        //如果不是超级管理员，则需要判断用户的角色是否自己创建
        if (user.getCreateUserId() == Constant.SUPER_ADMIN) {
            return;
        }

    }

    @Override
    @Transactional
    public Result stamp(StampVO stampVO) {
        return Result.ok();
    }

    private Result<String> uploadCard(StampVO stampVO, File downLoadFile) {
        return Result.ok();
    }

    @Override
    public Result wxLoginUser(Long userId) {
        checkIsOneself(userId);
        // 查询用户信息
        SysUserEntity sysUserEntity = this.baseMapper.selectById(userId);

        // 查询用户信息详情
        SysUserDetail sysUserDetail = sysUserDetailService.getOne(new QueryWrapper<SysUserDetail>().lambda().eq(SysUserDetail::getUserId, userId));

        WxLoginVO wxLoginVO = new WxLoginVO();
        if(sysUserEntity != null) {
            BeanUtils.copyProperties(sysUserEntity, wxLoginVO);
        }
        if(sysUserDetail != null) {
            BeanUtils.copyProperties(sysUserDetail, wxLoginVO);
        }
        addUnPassedMsg(wxLoginVO,sysUserEntity.getUserId());
        if (!StringUtils.isEmpty(sysUserEntity.getUserType()) && sysUserEntity.getUserType().contains(UserTypeEnums.VOL_USER.value())) {
            // 添加用户队伍
            getTeamIdsByUserId(wxLoginVO, userId);
            // 将用户等级告知
            List<SysRule> rules = sysRuleService.rules();
            String levelPic = getLevelPic(rules, sysUserDetail.getServiceHour());
            wxLoginVO.setLevelPic(levelPic);
        }
        return Result.ok().data(wxLoginVO);
    }

    @Override
    public Result wxImage(String verifyResult) {
        log.info("======获取accessToken========");
        String accessToken = (String) redisUtil.get("wxAccessToken");
        if (StringUtils.isEmpty(accessToken)) {
            accessToken = this.auth();
        }
        String imageUrl = wxImageUrl + accessToken;
        Map<String, String> headers = new HashMap<>();
        Map<String, Object> params = new HashMap<>();
        params.put("verify_result", verifyResult);
        byte[] imageByte = HttpClientUtils.getImageByte(imageUrl, headers, params);
        if (imageByte == null) {
            return Result.error("认证不通过,请重试");
        }
        //获取Base64
        String imageBase64 = Base64.getEncoder().encodeToString(imageByte);
        MultipartFile imgMultipartFile = Base64Utils.base64MultipartFile("data:image/jpeg;base64," + imageBase64);
        String photoUrl = minioUtils.uploadFileWithDayDir(imgMultipartFile, "joinval");
        return Result.ok().data(photoUrl);
    }

    @Override
    public void logo(Long userId, String logo) {
        AssertUtils.notNull(userId, "用户id主键不能为空");
        this.baseMapper.updateLogoById(logo, userId);
    }

    @Override
    public void addUserType(SysUserEntity sysUserEntity, UserTypeEnums userTypeEnums) {
        String userTypeOld = sysUserEntity.getUserType();
        if(!StringUtils.isEmpty(userTypeOld)){
            Set<String> userTypeSetCurrent = new HashSet<>(Arrays.asList(userTypeOld.split(",")));
            userTypeSetCurrent.add(userTypeEnums.value());
            if(userTypeSetCurrent.contains(UserTypeEnums.ORDER_USER.value()) || userTypeSetCurrent.contains(UserTypeEnums.VOL_USER.value())){
                userTypeSetCurrent.remove(UserTypeEnums.NORMAL_USER.value());
            }
            String userTypeNew = StringUtils.join(userTypeSetCurrent.toArray(), ",");
            sysUserEntity.setUserType(userTypeNew);
        }else {
            sysUserEntity.setUserType(userTypeEnums.value());
        }
    }
    @Override
    public void checkIsOneself(Long userId) {
        if(!ShiroUtils.getUserId().equals(userId)) {
            throw new RuntimeException("不是本人,无权限查看");
        }
    }

    public static String readFileContent(String fileName) {
        File file = new File(fileName);
        BufferedReader reader = null;
        StringBuffer sbf = new StringBuffer();
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempStr;
            while ((tempStr = reader.readLine()) != null) {
                sbf.append(tempStr);
            }
            reader.close();
            return sbf.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return sbf.toString();
    }

    private String auth() {
        Map<String, Object> accessTokenParams = new HashMap<>();
        accessTokenParams.put("grant_type", wxImageGrantType);
        accessTokenParams.put("appid", wxImageAppid);
        accessTokenParams.put("secret", wxImageSecret);
        String result = HttpClientUtils.sendGet(accessTokenUrl, accessTokenParams);
        if (StringUtils.isEmpty(result)) {
            throw new RuntimeException("网络异常,请重试");
        }
        JSONObject ret = JSONObject.parseObject(result);
        Integer errcode = ret.getInteger("errcode");
        if (errcode != null && !errcode.equals(0)) {
            throw new RuntimeException(ret.getString("errmsg"));
        }
        String accessToken = ret.getString("access_token");
        redisUtil.set("wxAccessToken", accessToken, 60 * 60 * 2);
        return accessToken;
    }

    public boolean checkVolUser(String idCard, String volCode) {
        VolUserDTO volUserDTO = this.baseMapper.queryVolUser(idCard, volCode);
        if (volUserDTO != null) {
            return false;
        }
        return true;
    }

    private boolean checkVolUser(String idCard, String volCode, Long sysUserId) {
        VolUserDTO volUserDTO = this.baseMapper.queryVolUser(idCard, volCode);
        if (volUserDTO != null && !volUserDTO.getUserId().equals(sysUserId)) {
            return false;
        }
        return true;
    }

    private static File generatePdfFile(MultipartFile ImgMultipartFile) throws Exception {
        String fileName = ImgMultipartFile.getOriginalFilename();
        String pdfFileName;
        if (fileName != null) {
            pdfFileName = fileName.substring(0, fileName.lastIndexOf(".")) + ".pdf";
        } else {
            return null;
        }
        final Rectangle EXP = new RectangleReadOnly(210f, 380);
        Document doc = new Document(EXP.rotate(), 50, 50, 50, 50);
        PdfWriter.getInstance(doc, new FileOutputStream(File.separator + "opt" + File.separator + "joinval_temp" + File.separator + pdfFileName));
        /** PdfWriter.getInstance(doc, new FileOutputStream("src/main/resources/temp/" + pdfFileName));*/
        doc.open();
        doc.newPage();
        Image image = Image.getInstance(ImgMultipartFile.getBytes());
        /* 设置图片的位置 */
        image.setAbsolutePosition(0, 0);
        /* 设置图片的大小 */
        //image.scaleAbsolute(595, 842);
        image.scaleAbsolute(380f, 210f);
        doc.add(image);
        doc.add(image);
        doc.close();

        float height = image.getHeight();
        float width = image.getWidth();
//      image.setAlignment(Image.MIDDLE);
//      image.scalePercent(percent);
        return new File(File.separator + "opt" + File.separator + "joinval_temp" + File.separator + pdfFileName);
        /** return new File("src/main/resources/temp/"+ pdfFileName);*/
    }

    private MultipartFile getMultipartFile(File pdfFile) {
//        FileItemFactory factory = new DiskFileItemFactory(16, null);
//        FileItem item=factory.createItem(pdfFile.getName(),"text/plain",true,pdfFile.getName());
//        System.out.println(item);
//        MultipartFile multipartFile = new CommonsMultipartFile(item);
//        return multipartFile;

        MultipartFile multipartFile = null;
        try {
            FileInputStream fileInputStream = new FileInputStream(pdfFile);
            multipartFile = new MockMultipartFile(pdfFile.getName(), pdfFile.getName(),
                    ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return multipartFile;
    }
}
